package com.example.vj.robotface_test;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Process;
import android.support.annotation.IdRes;
import android.support.annotation.StringDef;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.example.vj.robotface_test.util.FaceRect;
import com.example.vj.robotface_test.util.FaceUtil;
import com.example.vj.robotface_test.util.ParseResult;
import com.iflytek.cloud.FaceDetector;
import com.iflytek.cloud.util.Accelerometer;

import java.io.IOException;

/**
 * Created by vj on 17-9-26.
 */

public class FaceVideoDemo extends Activity {
    private final static String TAG = FaceVideoDemo.class.getSimpleName();
    private SurfaceView mPreviewSurface;
    private SurfaceView mFaceSurface;
    private Camera mCamera;
    private int mCameraId = android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT;

    private int PREVIEW_WIDTH = 640;
    private int PREVIEW_HEIGHT = 480;

    private byte[] nv21;
    private byte[] buffer;

    private Matrix mScaleMatrix = new Matrix();

    private Accelerometer mAcc;

    private FaceDetector mFaceDetector;
    private boolean mStopTrack;
    private Toast mToast;
    private long mLastCLickTime;
    private int isAlign = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_videodemo);

        initUI();

        nv21 = new byte[PREVIEW_WIDTH*PREVIEW_HEIGHT*2];
        buffer = new byte[PREVIEW_WIDTH*PREVIEW_HEIGHT*2];
        mAcc = new Accelerometer(FaceVideoDemo.this);
        mFaceDetector = FaceDetector.createDetector(FaceVideoDemo.this,null);
    }


    private SurfaceHolder.Callback mPreviewCallbak = new SurfaceHolder.Callback(){

        @Override
        public void surfaceDestroyed(SurfaceHolder holder)
        {
            closeCamera();
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder)
        {
            openCamera();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder,int format, int width, int height)
        {
            mScaleMatrix.setScale(width/(float)PREVIEW_HEIGHT,height/(float)PREVIEW_WIDTH);
        }

    };

    private void setSurfaceSize(){
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

        int width = metrics.widthPixels;
        int height = (int)(width*PREVIEW_WIDTH/(float)PREVIEW_HEIGHT);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width,height);
        params.addRule(RelativeLayout.ALIGN_PARENT_TOP);

        mPreviewSurface.setLayoutParams(params);
        mFaceSurface.setLayoutParams(params);
    }


    @SuppressLint("ShowToast")
    private void initUI(){
        mPreviewSurface = (SurfaceView)findViewById(R.id.sfv_preview);
        mFaceSurface = (SurfaceView)findViewById(R.id.sfv_face);

        mPreviewSurface.getHolder().addCallback(mPreviewCallbak);
        mPreviewSurface.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mFaceSurface.setZOrderOnTop(true);
        mFaceSurface.getHolder().setFormat(PixelFormat.TRANSLUCENT);

        mFaceSurface.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(Camera.getNumberOfCameras()==1)
                {
                    Toast.makeText(getApplicationContext(),"只有一个摄像头",Toast.LENGTH_SHORT).show();
                    return;
                }
                closeCamera();
                if(Camera.CameraInfo.CAMERA_FACING_FRONT==mCameraId)
                {
                    mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
                }
                else
                {
                    mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
                }
                openCamera();
            }
        });

        mFaceSurface.setOnTouchListener(new View.OnTouchListener()
        {
            @Override
            public boolean onTouch(View v, MotionEvent event)
            {
                switch (event.getAction())
                {
                    case MotionEvent.ACTION_DOWN:
                        mLastCLickTime = System.currentTimeMillis();
                        break;
                    case MotionEvent.ACTION_UP:
                        if(System.currentTimeMillis() - mLastCLickTime>500)
                        {
                            mCamera.autoFocus(null);
                            return true;
                        }
                        break;
                    default:
                        break;
                }
                return false;
            }
        });

        RadioGroup alignGroup = (RadioGroup)findViewById(R.id.aligen_mode);
        alignGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) {
                switch (i)
                {
                    case R.id.detect:
                        isAlign = 0;
                        break;
                    case R.id.aligen:
                        isAlign = 1;
                        break;
                    default:
                        break;
                }
            }
        });

        setSurfaceSize();

    }

    private void closeCamera()
    {
        if(null!=mCamera)
        {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera=null;
        }
    }

    private void openCamera()
    {
        if(null!=mCamera)
        {
            return;
        }
        if(!checkCameraPermission())
        {
            Toast.makeText(getApplicationContext(),"摄像头权限没打开，请打开后再试！",Toast.LENGTH_SHORT).show();
            mStopTrack = true;
            return;
        }

        if(Camera.getNumberOfCameras()==1)
        {
            mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;

        }

        try{
            mCamera = Camera.open(mCameraId);
            if(Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId)
            {
                Toast.makeText(getApplicationContext(),"前置摄像头已开启，点击可切换",Toast.LENGTH_SHORT).show();
            }
            else
            {
                Toast.makeText(getApplicationContext(),"后置摄像头已开启，点击可切换",Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e)
        {
            e.printStackTrace();
            closeCamera();
            return;
        }

        Camera.Parameters params = mCamera.getParameters();
        params.setPreviewFormat(ImageFormat.NV21);
        params.setPreviewSize(PREVIEW_WIDTH,PREVIEW_HEIGHT);
        mCamera.setParameters(params);

        mCamera.setDisplayOrientation(90);
        mCamera.setPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] bytes, Camera camera) {
                System.arraycopy(bytes,0,nv21,0,bytes.length);
            }
        });

        try{
            mCamera.setPreviewDisplay(mPreviewSurface.getHolder());
            mCamera.startPreview();
        } catch (IOException e)
        {
            e.printStackTrace();
        }

        if(mFaceDetector==null)
        {
            Toast.makeText(getApplicationContext(),"创建对象失败",Toast.LENGTH_SHORT).show();
        }

    }


    private boolean checkCameraPermission(){
        int status = checkPermission(Manifest.permission.CAMERA,Process.myPid(), Process.myUid());

        if(PackageManager.PERMISSION_GRANTED==status)
        {
            return true;
        }
        return false;
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (null != mAcc) {
            mAcc.start();
        }
        mStopTrack = false;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!mStopTrack) {
                    if (null == nv21) {
                        continue;
                    }

                    synchronized (nv21) {
                        System.arraycopy(nv21, 0, buffer, 0, nv21.length);
                    }

                    int direction = Accelerometer.getDirection();
                    boolean frontCamera = (Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId);

                    if (frontCamera) {
                        direction = (4 - direction) % 4;
                    }
                    if (mFaceDetector == null) {
                        Toast.makeText(getApplicationContext(), "创建对象失败", Toast.LENGTH_SHORT).show();
                        break;
                    }
                    String result  = mFaceDetector.trackNV21(buffer,PREVIEW_WIDTH,PREVIEW_HEIGHT,isAlign,direction);
                    Log.d(TAG,"result:"+result);

                    FaceRect[] faces = ParseResult.paraseResult(result);    //读取处理后的JASON里面的多个人脸位置信息和焦点信息

                    Canvas canvas = mFaceSurface.getHolder().lockCanvas();
                    if(null==canvas)
                    {
                        continue;
                    }
                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                    canvas.setMatrix(mScaleMatrix);

                    if(faces==null|| faces.length<=0)
                    {
                        mFaceSurface.getHolder().unlockCanvasAndPost(canvas);
                        continue;
                    }
                    if(null!=faces&&frontCamera==(Camera.CameraInfo.CAMERA_FACING_FRONT==mCameraId))
                    {
                        for(FaceRect face: faces)
                        {
                            face.bound = FaceUtil.RotateDeg90(face.bound,PREVIEW_WIDTH,PREVIEW_HEIGHT);
                            if(face.point != null)
                            {
                                for (int i = 0;i<face.point.length;i++)
                                {
                                    face.point[i]= FaceUtil.RotateDeg90(face.point[i],PREVIEW_WIDTH,PREVIEW_HEIGHT);
                                }
                            }
                            FaceUtil.drawFaceRect(canvas,face,PREVIEW_WIDTH,PREVIEW_HEIGHT,frontCamera,true);
                        }
                    }
                    else
                    {
                        Log.d(TAG,"faces:0");
                    }

                    mFaceSurface.getHolder().unlockCanvasAndPost(canvas);
                }
            }
        }).start();
    }
    @Override
    protected void onPause()
    {
        super.onPause();
        closeCamera();
        if(null!=mAcc)
        {
            mAcc.stop();
        }
        mStopTrack = true;
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        if(null!=mFaceDetector)
        {
            mFaceDetector.destroy();
        }
    }
}
